/**
 * Copyright (c) 2018-2023, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 *
 * Contains: 
 *
 * Change Logs:
 * Date           Author            Notes
 * 2023-07-29     Shiroko           Init
 */
#ifndef __DRIVERS_VIRTIO_DEVICES_VIRTIO_SOUND_H__
#define __DRIVERS_VIRTIO_DEVICES_VIRTIO_SOUND_H__

#define VIRTIO_SOUND_QUEUE_CONTROL  0
#define VIRTIO_SOUND_QUEUE_EVENT    1
#define VIRTIO_SOUND_QUEUE_TX       2
#define VIRTIO_SOUND_QUEUE_RX       3

/*
 * General enum and bits definitions
 */

enum VirtioSoundControlType
{
    /* jack control request types */
    VIRTIO_SND_R_JACK_INFO = 1,
    VIRTIO_SND_R_JACK_REMAP,

    /* PCM control request types */
    VIRTIO_SND_R_PCM_INFO = 0x0100,
    VIRTIO_SND_R_PCM_SET_PARAMS,
    VIRTIO_SND_R_PCM_PREPARE,
    VIRTIO_SND_R_PCM_RELEASE,
    VIRTIO_SND_R_PCM_START,
    VIRTIO_SND_R_PCM_STOP,

    /* channel map control request types */
    VIRTIO_SND_R_CHMAP_INFO = 0x0200,

    /* jack event types */
    VIRTIO_SND_EVT_JACK_CONNECTED = 0x1000,
    VIRTIO_SND_EVT_JACK_DISCONNECTED,

    /* PCM event types */
    VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED = 0x1100,
    VIRTIO_SND_EVT_PCM_XRUN,

    /* common status codes */
    VIRTIO_SND_S_OK = 0x8000,
    VIRTIO_SND_S_BAD_MSG,
    VIRTIO_SND_S_NOT_SUPP,
    VIRTIO_SND_S_IO_ERR
};
typedef enum VirtioSoundControlType               VirtioSoundControlType;

enum VirtioSoundDirection
{
    VIRTIO_SND_D_OUTPUT = 0,
    VIRTIO_SND_D_INPUT
};
typedef enum VirtioSoundDirection                 VirtioSoundDirection;

/* supported jack features */
#define VIRTIO_SND_JACK_FEATURE_REMAP  (1 << 0)

/* supported PCM stream features */
#define VIRTIO_SND_PCM_F_SHMEM_HOST         (1<<0)
#define VIRTIO_SND_PCM_F_SHMEM_GUEST        (1<<1)
#define VIRTIO_SND_PCM_F_MSG_POLLING        (1<<2)
#define VIRTIO_SND_PCM_F_EVT_SHMEM_PERIODS  (1<<3)
#define VIRTIO_SND_PCM_F_EVT_XRUNS          (1<<4)

/* supported PCM sample formats */
enum VirtioSoundPCMFormat
{
    /* analog formats (width / physical width) */
    VIRTIO_SND_PCM_FMT_IMA_ADPCM = 0,   /*  4 /  4 bits */
    VIRTIO_SND_PCM_FMT_MU_LAW,          /*  8 /  8 bits */
    VIRTIO_SND_PCM_FMT_A_LAW,           /*  8 /  8 bits */
    VIRTIO_SND_PCM_FMT_S8,              /*  8 /  8 bits */
    VIRTIO_SND_PCM_FMT_U8,              /*  8 /  8 bits */
    VIRTIO_SND_PCM_FMT_S16,             /* 16 / 16 bits */
    VIRTIO_SND_PCM_FMT_U16,             /* 16 / 16 bits */
    VIRTIO_SND_PCM_FMT_S18_3,           /* 18 / 24 bits */
    VIRTIO_SND_PCM_FMT_U18_3,           /* 18 / 24 bits */
    VIRTIO_SND_PCM_FMT_S20_3,           /* 20 / 24 bits */
    VIRTIO_SND_PCM_FMT_U20_3,           /* 20 / 24 bits */
    VIRTIO_SND_PCM_FMT_S24_3,           /* 24 / 24 bits */
    VIRTIO_SND_PCM_FMT_U24_3,           /* 24 / 24 bits */
    VIRTIO_SND_PCM_FMT_S20,             /* 20 / 32 bits */
    VIRTIO_SND_PCM_FMT_U20,             /* 20 / 32 bits */
    VIRTIO_SND_PCM_FMT_S24,             /* 24 / 32 bits */
    VIRTIO_SND_PCM_FMT_U24,             /* 24 / 32 bits */
    VIRTIO_SND_PCM_FMT_S32,             /* 32 / 32 bits */
    VIRTIO_SND_PCM_FMT_U32,             /* 32 / 32 bits */
    VIRTIO_SND_PCM_FMT_FLOAT,           /* 32 / 32 bits */
    VIRTIO_SND_PCM_FMT_FLOAT64,         /* 64 / 64 bits */
    /* digital formats (width / physical width) */
    VIRTIO_SND_PCM_FMT_DSD_U8,          /*  8 /  8 bits */
    VIRTIO_SND_PCM_FMT_DSD_U16,         /* 16 / 16 bits */
    VIRTIO_SND_PCM_FMT_DSD_U32,         /* 32 / 32 bits */
    VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME  /* 32 / 32 bits */
};
typedef enum VirtioSoundPCMFormat                 VirtioSoundPCMFormat;

/* supported PCM frame rates */
enum VirtioSoundPCMFramerate
{
    VIRTIO_SND_PCM_RATE_5512 = 0,
    VIRTIO_SND_PCM_RATE_8000,
    VIRTIO_SND_PCM_RATE_11025,
    VIRTIO_SND_PCM_RATE_16000,
    VIRTIO_SND_PCM_RATE_22050,
    VIRTIO_SND_PCM_RATE_32000,
    VIRTIO_SND_PCM_RATE_44100,
    VIRTIO_SND_PCM_RATE_48000,
    VIRTIO_SND_PCM_RATE_64000,
    VIRTIO_SND_PCM_RATE_88200,
    VIRTIO_SND_PCM_RATE_96000,
    VIRTIO_SND_PCM_RATE_176400,
    VIRTIO_SND_PCM_RATE_192000,
    VIRTIO_SND_PCM_RATE_384000
};
typedef enum VirtioSoundPCMFramerate              VirtioSoundPCMFramerate;

/* standard channel position definition */
enum VirtioSoundChannelPosition
{
    VIRTIO_SND_CHMAP_NONE = 0,  /* undefined */
    VIRTIO_SND_CHMAP_NA,        /* silent */
    VIRTIO_SND_CHMAP_MONO,      /* mono stream */
    VIRTIO_SND_CHMAP_FL,        /* front left */
    VIRTIO_SND_CHMAP_FR,        /* front right */
    VIRTIO_SND_CHMAP_RL,        /* rear left */
    VIRTIO_SND_CHMAP_RR,        /* rear right */
    VIRTIO_SND_CHMAP_FC,        /* front center */
    VIRTIO_SND_CHMAP_LFE,       /* low frequency (LFE) */
    VIRTIO_SND_CHMAP_SL,        /* side left */
    VIRTIO_SND_CHMAP_SR,        /* side right */
    VIRTIO_SND_CHMAP_RC,        /* rear center */
    VIRTIO_SND_CHMAP_FLC,       /* front left center */
    VIRTIO_SND_CHMAP_FRC,       /* front right center */
    VIRTIO_SND_CHMAP_RLC,       /* rear left center */
    VIRTIO_SND_CHMAP_RRC,       /* rear right center */
    VIRTIO_SND_CHMAP_FLW,       /* front left wide */
    VIRTIO_SND_CHMAP_FRW,       /* front right wide */
    VIRTIO_SND_CHMAP_FLH,       /* front left high */
    VIRTIO_SND_CHMAP_FCH,       /* front center high */
    VIRTIO_SND_CHMAP_FRH,       /* front right high */
    VIRTIO_SND_CHMAP_TC,        /* top center */
    VIRTIO_SND_CHMAP_TFL,       /* top front left */
    VIRTIO_SND_CHMAP_TFR,       /* top front right */
    VIRTIO_SND_CHMAP_TFC,       /* top front center */
    VIRTIO_SND_CHMAP_TRL,       /* top rear left */
    VIRTIO_SND_CHMAP_TRR,       /* top rear right */
    VIRTIO_SND_CHMAP_TRC,       /* top rear center */
    VIRTIO_SND_CHMAP_TFLC,      /* top front left center */
    VIRTIO_SND_CHMAP_TFRC,      /* top front right center */
    VIRTIO_SND_CHMAP_TSL,       /* top side left */
    VIRTIO_SND_CHMAP_TSR,       /* top side right */
    VIRTIO_SND_CHMAP_LLFE,      /* left LFE */
    VIRTIO_SND_CHMAP_RLFE,      /* right LFE */
    VIRTIO_SND_CHMAP_BC,        /* bottom center */
    VIRTIO_SND_CHMAP_BLC,       /* bottom left center */
    VIRTIO_SND_CHMAP_BRC        /* bottom right center */
};

/* maximum possible number of channels */
#define VIRTIO_SND_CHMAP_MAX_SIZE 18

/*
 * General control & event structure
 */

struct VirtioSoundControlHeader
{
    NX_U32 code;
    char   data[0];
};
typedef struct VirtioSoundControlHeader           VirtioSoundControlHeader;

/* an event notification */
struct VirtioSoundEvent
{
    VirtioSoundControlHeader header;
    NX_U32                   data;
};
typedef struct VirtioSoundEvent                   VirtioSoundEvent;

/*
 * Command: Query JACK/PCM/CHMAP Info
 */

struct VirtioSoundRequestQueryInfoHeader
{
    VirtioSoundControlHeader header;
    NX_U32                   start_id;
    NX_U32                   count;
    NX_U32                   size;
};
typedef struct VirtioSoundRequestQueryInfoHeader  VirtioSoundRequestQueryInfoHeader;

struct VirtioSoundResponseQueryInfoHeader
{
    NX_U32 hda_fn_nid;
};
typedef struct VirtioSoundResponseQueryInfoHeader VirtioSoundResponseQueryInfoHeader;

struct VirtioSoundResponseQueryJackInfo
{
    VirtioSoundResponseQueryInfoHeader header;
    NX_U32                             features;
    NX_U32                             hda_reg_defconf;
    NX_U32                             hda_reg_caps;
    NX_U8                              connected;

    NX_U8 padding[7];
};
typedef struct VirtioSoundResponseQueryJackInfo   VirtioSoundResponseQueryJackInfo;

struct VirtioSoundPCMInfo
{
    NX_U32 features;
    NX_U64 formats;
    NX_U64 rates;
    NX_U8  direction;
    NX_U8  channels_min;
    NX_U8  channels_max;
}__attribute__((packed));
typedef struct VirtioSoundPCMInfo                 VirtioSoundPCMInfo;

struct VirtioSoundResponseQueryPCMInfo
{
    VirtioSoundResponseQueryInfoHeader header;
    VirtioSoundPCMInfo                 pcmInfo;
    NX_U8                              padding[5];
};
typedef struct VirtioSoundResponseQueryPCMInfo    VirtioSoundResponseQueryPCMInfo;

struct VirtioSoundResponseQueryChmapInfo
{
    VirtioSoundResponseQueryInfoHeader header;
    NX_U8                              direction;
    NX_U8                              channels;
    NX_U8                              positions[VIRTIO_SND_CHMAP_MAX_SIZE];
};
typedef struct VirtioSoundResponseQueryChmapInfo  VirtioSoundResponseQueryChmapInfo;

/*
 * Command: Jack Request (exclude info request)
 */

struct VirtioSoundJackHeader
{
    VirtioSoundControlHeader header;
    NX_U32                   jack_id;
};
typedef struct VirtioSoundJackHeader              VirtioSoundJackHeader;

struct VirtioSoundRequestJackRemap
{
    VirtioSoundJackHeader jackHeader;
    NX_U32                association;
    NX_U32                sequence;
};
typedef struct VirtioSoundRequestJackRemap        VirtioSoundRequestJackRemap;

/*
 * Command: PCM Request (exclude info request)
 */

struct VirtioSoundPCMHeader
{
    VirtioSoundControlHeader header;
    NX_U32                   stream_id;
};
typedef struct VirtioSoundPCMHeader               VirtioSoundPCMHeader;

struct VirtioSoundPCMParameters
{
    NX_U32 buffer_bytes;
    NX_U32 period_bytes;
    NX_U32 features;
    NX_U8  channels;
    NX_U8  format;
    NX_U8  rate;
}__attribute__((packed));
typedef struct VirtioSoundPCMParameters           VirtioSoundPCMParameters;

struct VirtioSoundRequestPCMSetParams
{
    VirtioSoundPCMHeader     pcmHeader;
    VirtioSoundPCMParameters parameters;
    NX_U8                    padding;
};
typedef struct VirtioSoundRequestPCMSetParams     VirtioSoundRequestPCMSetParams;

/* an I/O header */
struct VirtioSoundPCMIOHeader
{
    NX_U32 stream_id;
};
typedef struct VirtioSoundPCMIOHeader             VirtioSoundPCMIOHeader;

/* an I/O status */
struct VirtioSoundPCMIOStatus
{
    NX_U32 status;
    NX_U32 latency_bytes;
};
typedef struct VirtioSoundPCMIOStatus             VirtioSoundPCMIOStatus;

/*
 * Command: ChannelMap Request (exclude info)
 * Current none
 */


struct VirtioSoundDeviceConfig
{
    NX_U32 jacks;
    NX_U32 streams;
    NX_U32 chmaps;
};
typedef struct VirtioSoundDeviceConfig            VirtioSoundDeviceConfig;

enum VirtioSoundDeviceStatus
{
    VIRTIO_SOUND_DEVICE_INITIALIZED,
    VIRTIO_SOUND_DEVICE_OPENED,
    VIRTIO_SOUND_DEVICE_PREPARED,
    VIRTIO_SOUND_DEVICE_STARTED,
    VIRTIO_SOUND_DEVICE_STOPPED,
    VIRTIO_SOUND_DEVICE_RELEASED,
    VIRTIO_SOUND_DEVICE_CLOSED = VIRTIO_SOUND_DEVICE_INITIALIZED,
};
typedef enum VirtioSoundDeviceStatus              VirtioSoundDeviceStatus;

struct VirtioSoundDeviceExtension
{
    VirtioSoundDeviceConfig *deviceConfig;
    VirtioSoundPCMInfo      *pcmStreamsInfo;
    NX_U32                  selectedStreamId;
    VirtioSoundDeviceStatus deviceStatus;
    NX_U32                  buffer_size;
    NX_U32                  period_size;
    VirtioSoundEvent        *events;
    NX_Fifo                 *result_buffer;
};
typedef struct VirtioSoundDeviceExtension         VirtioSoundDeviceExtension;

/*
 * Public interface
 */

struct VirtioSoundCmdPCMSetParam
{
    NX_U32 streamId;
    NX_U32 buffer_bytes;
    NX_U32 period_bytes;
    NX_U32 features;
    NX_U8  channels;
    NX_U8  format;
    NX_U8  rate;
};
typedef struct VirtioSoundCmdPCMSetParam          VirtioSoundCmdPCMSetParam;

struct VirtioSoundCmdGetPCMInfo
{
    NX_U32 streamId;
    NX_U32 features;
    NX_U64 formats;
    NX_U64 rates;
    NX_U8  direction;
    NX_U8  channels_min;
    NX_U8  channels_max;
};
typedef struct VirtioSoundCmdGetPCMInfo           VirtioSoundCmdGetPCMInfo;

#define VIRTIO_SOUND_CMD_PCM_SELECT_STREAM  0x100   // arg = NX_U32 (streamId)
#define VIRTIO_SOUND_CMD_PCM_SET_PARAM      0x101   // arg = VirtioSoundCmdPCMSetParam
#define VIRTIO_SOUND_CMD_PCM_PREPARE        0x102   // arg = NX_U32 (streamId) / NX_NULL
#define VIRTIO_SOUND_CMD_PCM_START          0x103   // arg = NX_U32 (streamId) / NX_NULL
#define VIRTIO_SOUND_CMD_PCM_STOP           0x104   // arg = NX_U32 (streamId) / NX_NULL
#define VIRTIO_SOUND_CMD_PCM_RELEASE        0x105   // arg = NX_U32 (streamId) / NX_NULL

#define VIRTIO_SOUND_CMD_GET_PCM_INFO       0x110   // arg = VirtioSoundCmdGetPCMInfo


#endif // __DRIVERS_VIRTIO_DEVICES_VIRTIO_SOUND_H__
